﻿using MvCameraControl;
using Newtonsoft.Json;
using System.ComponentModel;
using System.Net;
using System.Windows;
using System.Windows.Threading;
using VisionDesigner;
using VM.Common.Helper;
using VM.Core;
using VM.Models;
using VM.Scheme;


namespace Plugin.CameraHikVision
{
    [Category("相机")]
    [DisplayName("海康相机")]
    [JsonObject(MemberSerialization.OptOut)]
    public class CameraHikVision : CameraBase
    {
        /// <summary> 
        /// 初始化
        /// </summary>
        public CameraHikVision()
        {
            // ch: 初始化 SDK | en: Initialize SDK
            SDKSystem.Initialize();
            IDevice device = null;
            _imageProcessor = new DefaultImageProcessor(new VM.Controls.DisplayControl()); // 使用默认图像处理器
            FrameReady += ProcessFrameOnMainThread; // 订阅事件
            _syncContext = SynchronizationContext.Current;

        }
        #region 属性
        // ch:枚举的相机类型 | en:TLayerType for enumerate devices
        readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice
    | DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvGenTLCXPDevice | DeviceTLayerType.MvGenTLCameraLinkDevice | DeviceTLayerType.MvGenTLXoFDevice;

        // 进程取图
        bool isGrabbing = false;        // ch:是否正在取图 | en: Grabbing flag
        Thread receiveThread = null;    // ch:接收图像线程 | en: Receive image thread

        List<IDeviceInfo> deviceInfoList = new List<IDeviceInfo>();
        IDevice device = null;
        private Thread reconnectThread = null;
        private IImage? _processingFrame; // 正在处理的帧
        private IImage? _readyFrame;     // 最新接收到的帧
        private readonly object _bufferLock = new(); // 双缓冲区锁

        private DispatcherTimer _processTimer; // 使用 DispatcherTimer
        private IIntValue intValue;

        public enum AcquisitionMode
        {
            Single,     // 单次采集
            Continuous  // 连续采集
        }

        private AcquisitionMode _acquisitionMode = AcquisitionMode.Single; // 当前采集模式
        private bool _isContinuousRunning = false; // 是否处于连续采集状态
        private bool ContinuousProcessFlag = false;

        // ManualResetEvent 用于线程同步
        private readonly ManualResetEvent _frameReadyEvent = new ManualResetEvent(false);

        // 定义事件
        public event Action<IImage?>? FrameReady;
        private SynchronizationContext? _syncContext;

        #endregion
        #region 相机使用方法

        /// <summary>
        /// 搜索相机
        /// </summary>
        /// <returns></returns>
        public override List<CameraInfoModel> SearchCameras()
        {
            var cameraInfoList = new List<CameraInfoModel>();
            try
            {
                // 枚举设备
                int result = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList);
                if (result != MvError.MV_OK || deviceInfoList == null)
                {
                    // 枚举失败或设备列表为空
                    string ErrorMsg = "Enumerate devices failed!";
                    return cameraInfoList;
                }

                // 遍历设备信息
                for (int i = 0; i < deviceInfoList.Count; i++)
                {
                    var deviceInfo = deviceInfoList[i];
                    if (deviceInfo == null)
                        continue;

                    if (deviceInfo.TLayerType == DeviceTLayerType.MvGigEDevice || deviceInfo.TLayerType == DeviceTLayerType.MvVirGigEDevice || deviceInfo.TLayerType == DeviceTLayerType.MvGenTLGigEDevice)
                    {
                        IGigEDeviceInfo gigeDevInfo = deviceInfo as IGigEDeviceInfo;
                        uint nIp1 = ((gigeDevInfo.CurrentIp & 0xff000000) >> 24);
                        uint nIp2 = ((gigeDevInfo.CurrentIp & 0x00ff0000) >> 16);
                        uint nIp3 = ((gigeDevInfo.CurrentIp & 0x0000ff00) >> 8);
                        uint nIp4 = (gigeDevInfo.CurrentIp & 0x000000ff);
                        CameraIP = $"{nIp1}.{nIp2}.{nIp3}.{nIp4}";
                    }

                    var cameraInfo = new CameraInfoModel
                    {
                        CameraIndex = i,
                        CameraIP = CameraIP,
                        CamName = !string.IsNullOrEmpty(deviceInfo.UserDefinedName)
                            ? deviceInfo.UserDefinedName
                            : deviceInfo.ManufacturerName + " " + deviceInfo.ModelName,
                        SerialNO = $"{deviceInfo.TLayerType}: {(string.IsNullOrEmpty(deviceInfo.UserDefinedName) ? deviceInfo.ManufacturerName + " " + deviceInfo.ModelName : deviceInfo.UserDefinedName)} ({deviceInfo.SerialNumber})",
                        ExtInfo = deviceInfo
                    };

                    cameraInfoList.Add(cameraInfo);
                }
            }
            catch (Exception ex)
            {
                // 捕获并记录异常
                string ErrorMsg = $"Error occurred while searching cameras: {ex.Message}";
            }

            return cameraInfoList;

        }

        /// <summary>释放设备资源</summary>
        private void DisposeDevice()
        {
            if (device != null)
            {
                device.StreamGrabber.StopGrabbing();
                device.Close();
                device.Dispose();
                device = null;
            }
        }

        /// <summary>配置 GigE 设备的最佳包大小</summary>
        private void ConfigureGigEDevice()
        {
            if (device is IGigEDevice gigEDevice)
            {
                try
                {
                    if (gigEDevice.GetOptimalPacketSize(out int packetSize) == MvError.MV_OK)
                    {
                        if (device.Parameters.SetIntValue("GevSCPSPacketSize", (long)packetSize) != MvError.MV_OK)
                        {
                            //LogWarning("Set Packet Size failed!");
                        }
                    }
                    else
                    {
                        //LogWarning("Get Packet Size failed!");
                    }
                }
                catch (Exception ex)
                {
                    //LogWarning($"ConfigureGigEDevice failed: {ex.Message}");
                }
            }
        }

        /// <summary>配置单次采集模式</summary>
        private void ConfigureSingleCollectionMode()
        {
            try
            {
                // ch:打开触发模式 | en:Open Trigger Mode
                device.Parameters.SetEnumValueByString("TriggerMode", "On");
                device.Parameters.SetEnumValueByString("TriggerSource", "Software");
                // ch:触发命令 | en:Trigger command
                int result = device.Parameters.SetCommandValue("TriggerSoftware");
                if (result != MvError.MV_OK)
                {
                    //ShowErrorMsg("Trigger Software Fail!", result);
                }
                _acquisitionMode = AcquisitionMode.Single;
            }
            catch (Exception ex)
            {
                //LogWarning($"ConfigureAcquisitionMode failed: {ex.Message}");
            }
        }

        /// <summary>配置连续采集模式</summary>
        private void ConfigureAcquisitionMode()
        {
            try
            {
                if (device != null && device.Parameters != null)
                {
                    device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
                    device.Parameters.SetEnumValueByString("TriggerMode", "Off");
                    _acquisitionMode = AcquisitionMode.Continuous;
                }

            }
            catch (Exception ex)
            {
                //LogWarning($"ConfigureAcquisitionMode failed: {ex.Message}");
            }
        }

        /// <summary>注册设备事件</summary>
        private void RegisterDeviceEvents()
        {
            device.StreamGrabber.SetImageNodeNum(5);  // 设置缓存节点数量
            device.StreamGrabber.FrameGrabedEvent += FrameGrabedEventHandler; // 帧抓取事件
            device.DeviceExceptionEvent += ExceptionEventHandler; // 异常事件
        }

        /// <summary>连接相机</summary>
        public override void ConnectDev()
        {
            try
            {// 异步更新到 UI，确保线程安全
                Application.Current.Dispatcher.Invoke(() =>
                {
                    VM.Start.ViewModels.Dock.VisionViewModel.Ins.ShowImage = new CMvdImage();
                    _imageProcessor._displayControl.MVDRender.ClearImages();
                    _imageProcessor._displayControl.MVDRender.ClearShapes();
                    _imageProcessor._displayControl.AddedShapes.Clear();
                    _imageProcessor._displayControl._addedShapes.Clear();
                    _imageProcessor.UnbindEvents();
                });
                // 如果设备已存在，先释放资源
                DisposeDevice();
                // 创建新设备实例
                device = DeviceFactory.CreateDevice((IDeviceInfo)ExtInfo);

                // 打开设备
                int result = device.Open();
                if (result != MvError.MV_OK)
                {
                    //LogError("Open Device failed!");
                    Connected = false;
                    return;
                }

                // 如果是 GigE 设备，设置最佳包大小
                ConfigureGigEDevice();

                // 设置采集模式为连续模式
                ConfigureAcquisitionMode();

                // 设置设备参数
                SetSetting();
                GetParams();

                //// 注册事件
                //RegisterDeviceEvents();

                // 开始取流
                Connected = StartGrabbing(AcquisitionMode.Continuous);
                // 启动自动重连线程
                _bExit = false;
                if (Connected)
                {
                    reconnectThread = new Thread(ReconnectProcess)
                    {
                        IsBackground = true // 设置为后台线程
                    };
                    reconnectThread.Start();
                }
            }
            catch (Exception ex)
            {
                string ErrorMsg = "Create Device fail!" + ex.Message;
                Connected = false;
                return;
            }
        }

        /// <summary>断开相机</summary>
        public override void DisConnectDev()
        {
            // 停止采集
            try
            {
                if (_acquisitionMode == AcquisitionMode.Single)
                {
                    Connected = !StopGrabbing(AcquisitionMode.Single);
                }
                else
                {
                    Connected = !StopGrabbing(AcquisitionMode.Continuous);
                }

                _bExit = true;
                reconnectThread?.Join();
                // ch:关闭设备 | en:Close Device
                if (device != null)
                {
                    device.Close();
                    device.Dispose();
                    device = null;
                }
            }
            catch (MvdException ex)
            {

            }
        }

        /// <summary>
        /// 相机开始取流
        /// </summary>
        /// <returns></returns>
        private bool StartGrabbing(AcquisitionMode mode)
        {
            // 检查 device 是否已销毁
            if (device == null)
            {
                //LogError("Device is null or already disposed. Unable to start grabbing.");
                return false;
            }

            try
            {
                if (mode == AcquisitionMode.Continuous)
                {
                    isGrabbing = true;
                    receiveThread = new Thread(ReceiveThreadProcess);
                    receiveThread.Start();
                    // 开启抓图
                    int ret = device.StreamGrabber.StartGrabbing();
                    if (ret != MvError.MV_OK)
                    {
                        isGrabbing = false;
                        receiveThread.Join();
                        //LogError($"Start grabbing failed: {ret:x8}");
                        return false;
                    }
                }
                else
                {
                    // 开启抓图
                    int ret = device.StreamGrabber.StartGrabbing();
                    if (ret != MvError.MV_OK)
                    {
                        //LogError($"Start grabbing failed: {ret:x8}");
                        return false;
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                //LogError($"Exception occurred while starting grabbing: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 相机停止取流
        /// </summary>
        /// <returns></returns>
        private bool StopGrabbing(AcquisitionMode mode)
        {
            // 检查 device 是否已销毁
            if (device == null)
            {
                //LogError("Device is null or already disposed. Unable to stop grabbing.");
                return true;
            }

            try
            {
                if (mode == AcquisitionMode.Continuous)
                {
                    isGrabbing = false;
                    _isContinuousRunning = false;
                    if (receiveThread != null && receiveThread.IsAlive)
                    {
                        if (!receiveThread.Join(5000)) // 等待线程结束，超时 5 秒
                        {
                            Console.WriteLine("Thread did not terminate in time.");
                            return false;
                        }
                    }
                }
                // 停止抓图
                int ret = device.StreamGrabber.StopGrabbing();
                if (ret != MvError.MV_OK)
                {
                    //LogError($"Stop grabbing failed: {ret:x8}");
                    return true;
                }
                return true;
            }
            catch (Exception ex)
            {
                //LogError($"Exception occurred while stopping grabbing: {ex.Message}");
                return true;
            }
        }

        public override IPConfig GetIpConfig()
        {
            IPConfig ipConfig = new IPConfig();

            if (ExtInfo is not IGigEDeviceInfo gigeDevInfo)
                return ipConfig;

            // Helper function to format an IP address from a 32-bit integer
            static string FormatIp(uint ip)
            {
                return $"{(ip >> 24) & 0xFF}.{(ip >> 16) & 0xFF}.{(ip >> 8) & 0xFF}.{ip & 0xFF}";
            }

            // 网口 IP 范围 (确保低 8 位清零后生成正确的 IP 段)
            uint netExportBase = gigeDevInfo.NetExport & 0xFFFFFF00;
            string netBaseIp = FormatIp(netExportBase);
            ipConfig.IpRange = $"{netBaseIp}~{FormatIp(netExportBase | 0xFF)}";

            // 当前 IP
            ipConfig.CurrentIP = FormatIp(gigeDevInfo.CurrentIp);
            CameraIP = ipConfig.CurrentIP;

            // 子网掩码
            ipConfig.SubnetMask = FormatIp(gigeDevInfo.CurrentSubNetMask);

            // 默认网关
            ipConfig.DefaultGateway = FormatIp(gigeDevInfo.DefultGateWay);

            return ipConfig;
        }

        public override void SetIpConfig(IPConfig iPConfig)
        {

            // ch:IP转换 | en:IP conversion
            IPAddress clsIpAddr;
            if (false == IPAddress.TryParse(iPConfig.CurrentIP, out clsIpAddr))
            {
                //ShowErrorMsg("Please enter correct IP", 0);
                return;
            }
            long nIp = IPAddress.NetworkToHostOrder(clsIpAddr.Address);

            // ch:掩码转换 | en:Mask conversion
            IPAddress clsSubMask;
            if (false == IPAddress.TryParse(iPConfig.SubnetMask, out clsSubMask))
            {
                //ShowErrorMsg("Please enter correct IP", 0);
                return;
            }
            long nSubMask = IPAddress.NetworkToHostOrder(clsSubMask.Address);

            // ch:网关转换 | en:Gateway conversion
            IPAddress clsDefaultWay;
            if (false == IPAddress.TryParse(iPConfig.DefaultGateway, out clsDefaultWay))
            {
                //ShowErrorMsg("Please enter correct IP", 0);
                return;
            }
            long nDefaultWay = IPAddress.NetworkToHostOrder(clsDefaultWay.Address);

            if (ExtInfo == null)
            {
                return;
            }
            int ret = MvError.MV_OK;
            // ch:创建设备 | en:Create device
            device = DeviceFactory.CreateDevice((IDeviceInfo)ExtInfo);
            IGigEDevice gigeDevice = device as IGigEDevice;
            // ch:判断设备IP是否可达 | en: If device ip is accessible
            bool accessible = DeviceEnumerator.IsDeviceAccessible((IDeviceInfo)ExtInfo, DeviceAccessMode.AccessExclusive);
            if (accessible)
            {
                ret = gigeDevice.SetIpConfig(IpConfigType.Static);
                if (MvError.MV_OK != ret)
                {
                    //ShowErrorMsg("Set Ip config fail", ret);
                    gigeDevice.Dispose();
                    device = null;
                    return;
                }
                ret = gigeDevice.ForceIp((uint)(nIp >> 32), (uint)(nSubMask >> 32), (uint)(nDefaultWay >> 32));
                if (MvError.MV_OK != ret)
                {
                    //ShowErrorMsg("ForceIp fail", ret);
                    gigeDevice.Dispose();
                    device = null;
                    return;
                }
            }
            else
            {
                ret = gigeDevice.ForceIp((uint)(nIp >> 32), (uint)(nSubMask >> 32), (uint)(nDefaultWay >> 32));
                if (MvError.MV_OK != ret)
                {
                    //ShowErrorMsg("ForceIp fail", ret);
                    gigeDevice.Dispose();
                    device = null;
                    return;
                }
                gigeDevice.Dispose();

                IDeviceInfo deviceInfo = (IDeviceInfo)ExtInfo;
                IGigEDeviceInfo gigeDevInfo = deviceInfo as IGigEDeviceInfo;

                uint nIp1 = ((gigeDevInfo.NetExport & 0xff000000) >> 24);
                uint nIp2 = ((gigeDevInfo.NetExport & 0x00ff0000) >> 16);
                uint nIp3 = ((gigeDevInfo.NetExport & 0x0000ff00) >> 8);
                uint nIp4 = (gigeDevInfo.NetExport & 0x000000ff);
                string netExportIp = nIp1.ToString() + "." + nIp2.ToString() + "." + nIp3.ToString() + "." + nIp4.ToString();
                //ch:需要重新创建句柄，设置为静态IP方式进行保存 | en:  Need to recreate the handle and set it to static IP mode for saving
                //ch: 创建设备 | en: Create device
                device = DeviceFactory.CreateDeviceByIp(iPConfig.CurrentIP, netExportIp);
                if (null == device)
                {
                    //ShowErrorMsg("Create handle fail", 0);
                    return;
                }
                gigeDevice = device as IGigEDevice;
                ret = gigeDevice.SetIpConfig(IpConfigType.Static);
                if (MvError.MV_OK != ret)
                {
                    //ShowErrorMsg("Set Ip config fail", ret);
                    gigeDevice.Dispose();
                    device = null;
                    return;
                }
            }
            // 枚举设备
            if (TryEnumDevices(out var deviceInfoList))
            {
                // 匹配序列号并更新 ExtInfo
                var matchingDevice = deviceInfoList.FirstOrDefault(item =>
                    (ExtInfo as IDeviceInfo)?.SerialNumber == item.SerialNumber);

                if (matchingDevice != null)
                {
                    ExtInfo = matchingDevice;
                }
            }
        }

        #endregion
        #region 事件


        private MvGvspPixelType DeterminePixelType(MvGvspPixelType pixelType)
        {
            if (IsColorPixelFormat(pixelType))
            {
                return MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
            }
            if (IsMonoPixelFormat(pixelType))
            {
                return MvGvspPixelType.PixelType_Gvsp_Mono8;
            }
            return MvGvspPixelType.PixelType_Gvsp_Undefined;
        }

        /// <summary>
        /// 相机取流回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FrameGrabedEventHandler(object sender, FrameGrabbedEventArgs e)
        {

            // ch: 克隆图像数据（深拷贝） | en :Clone frame data using deep copy
            IImage? outImage = null;
            try
            {
                MvGvspPixelType dstPixelType = MvGvspPixelType.PixelType_Gvsp_Undefined;

                if (IsColorPixelFormat(e.FrameOut.Image.PixelType))
                {
                    dstPixelType = MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
                }
                else if (IsMonoPixelFormat(e.FrameOut.Image.PixelType))
                {
                    dstPixelType = MvGvspPixelType.PixelType_Gvsp_Mono8;
                }

                if (dstPixelType != MvGvspPixelType.PixelType_Gvsp_Undefined)
                {
                    int result = device.PixelTypeConverter.ConvertPixelType(e.FrameOut.Image, out outImage, dstPixelType);
                    if (result != MvError.MV_OK)
                    {
                        Console.WriteLine($"Image Convert failed: {result:x8}");
                        return;
                    }
                }
                else
                {
                    outImage = e.FrameOut.Image;
                }

                lock (_bufferLock)
                {
                    _readyFrame = outImage;
                }
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// 连续采集取图进程
        /// </summary>
        public void ReceiveThreadProcess()
        {
            IFrameOut frameOut = null;
            IImage? outImage = null;
            int result = MvError.MV_OK;

            while (isGrabbing)
            {
                try
                {
                    result = device.StreamGrabber.GetImageBuffer(1000, out frameOut);
                    if (result == MvError.MV_OK)
                    {
                        MvGvspPixelType dstPixelType = DeterminePixelType(frameOut.Image.PixelType);

                        if (dstPixelType != MvGvspPixelType.PixelType_Gvsp_Undefined)
                        {
                            result = device.PixelTypeConverter.ConvertPixelType(frameOut.Image, out outImage, dstPixelType);
                            if (result != MvError.MV_OK)
                            {
                                Console.WriteLine($"Image Convert failed: {result:x8}");
                                return;
                            }
                        }
                        else
                        {
                            outImage = frameOut.Image;
                        }

                        // 处理连续采集逻辑
                        if (_acquisitionMode == AcquisitionMode.Continuous && _isContinuousRunning && !ContinuousProcessFlag)
                        {
                            ContinuousProcessFlag = true;
                            FrameReady?.Invoke(outImage);
                        }

                        device.StreamGrabber.FreeImageBuffer(frameOut);
                    }
                }
                catch (Exception ex)
                {

                }
            }
        }

        /// <summary>采集图像,是否手动采图</summary>
        public override bool CaptureSingleImage()
        {
            try
            {
                if (_acquisitionMode != AcquisitionMode.Single)
                {
                    //SetFrameRate(FrameRate, false);
                    StopGrabbing(AcquisitionMode.Continuous);
                    ConfigureSingleCollectionMode();
                    Connected = StartGrabbing(AcquisitionMode.Single);
                }

                // ch:触发命令 | en:Trigger command
                int result = device.Parameters.SetCommandValue("TriggerSoftware");
                if (result != MvError.MV_OK)
                {
                    //ShowErrorMsg("Trigger Software Fail!", result);
                }

                IFrameOut frameOut = null;
                IImage? outImage = null;
                result = device.StreamGrabber.GetImageBuffer(1000, out frameOut);
                if (result == MvError.MV_OK)
                {
                    MvGvspPixelType dstPixelType = DeterminePixelType(frameOut.Image.PixelType);

                    if (dstPixelType != MvGvspPixelType.PixelType_Gvsp_Undefined)
                    {
                        result = device.PixelTypeConverter.ConvertPixelType(frameOut.Image, out outImage, dstPixelType);
                        if (result != MvError.MV_OK)
                        {
                            Console.WriteLine($"Image Convert failed: {result:x8}");
                            return false;
                        }
                    }
                    else
                    {
                        outImage = frameOut.Image;
                    }
                    ProcessFrame(outImage);
                    device.StreamGrabber.FreeImageBuffer(frameOut);
                }

                return true;

            }
            catch (MvdException ex)
            {
                return false;
            }
            finally
            {
                EventWait.Set();
            }
        }

        public override bool CaptureContinualImage(bool flag)
        {
            //注册定时器事件
            if (_acquisitionMode != AcquisitionMode.Continuous)
            {
                StopGrabbing(AcquisitionMode.Single);
                ConfigureAcquisitionMode();
                Connected = StartGrabbing(AcquisitionMode.Continuous);
            }
            //SetFrameRate(FrameRate, flag);
            _isContinuousRunning = flag;

            return true;
        }

        // 主线程中处理帧
        private void ProcessFrameOnMainThread(IImage? frame)
        {
            Task.Run(() =>
            {
                try
                {
                    ProcessFrame(frame);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error in ProcessFrame (Continuous): {ex.Message}");
                }
                finally
                {
                    ContinuousProcessFlag = false;
                }
            });
        }

        /// <summary>
        /// 处理采集的帧数据
        /// </summary>
        /// <param name="frame"></param>
        private void ProcessFrame(IImage frame)
        {

            try
            {
                // 转换帧数据为内部图像格式
                ImageTool.GetImvdImgFromCamerData(
                    frame.Width,
                    frame.Height,
                    frame.PixelData,
                    frame.PixelType,
                    ref Image
                );

                // 调用图像处理器处理数据
                _imageProcessor.ProProcess();
                _imageProcessor.ProcessImage(Image);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in ProcessFrame: " + ex.Message);
            }

        }

        ///// <summary>
        ///// DispatcherTimer 的 Tick 事件处理
        ///// </summary>
        //private void ProcessTimer_Tick(object? sender, EventArgs e)
        //{
        //    if (_acquisitionMode == AcquisitionMode.Continuous && _isContinuousRunning)
        //    {
        //        IImage? frameToProcess = null;

        //        // 从缓冲区中取出最近的一帧
        //        lock (_bufferLock)
        //        {
        //            if (_readyFrame != null)
        //            {
        //                frameToProcess = _readyFrame;
        //                _readyFrame = null; // 取出后清空缓冲
        //            }
        //        }

        //        // 如果有帧可处理，则处理
        //        if (frameToProcess != null)
        //        {
        //            try
        //            {

        //                ProcessFrame(frameToProcess); // 自定义处理逻辑
        //            }
        //            catch (Exception ex)
        //            {
        //                Console.WriteLine($"ProcessFrame Error: {ex.Message}");
        //            }
        //        }
        //    }
        //}

        /// <summary>
        /// 自动重连
        /// </summary>
        public void ReconnectProcess()
        {
            int ret = MvError.MV_OK;

            while (!_bExit)
            {
                if (_bConnect)
                {
                    Thread.Sleep(10);
                    continue;
                }

                if (device != null)
                {
                    device.StreamGrabber.StopGrabbing();
                    device.Close();
                    device.Dispose();
                    device = null;
                }

                // 枚举设备
                if (!TryEnumDevices(out var deviceInfoList))
                {
                    Thread.Sleep(1000); // 等待 1 秒后重试
                    continue;
                }

                // 查找匹配的设备
                var matchedDevice = FindDevice(deviceInfoList, SerialNo);
                if (matchedDevice == null)
                {
                    //LogError("No matching device found.");
                    Thread.Sleep(1000); // 等待 1 秒后重试
                    continue;
                }

                // 创建并打开设备
                device = DeviceFactory.CreateDevice(matchedDevice);
                ret = device.Open();
                if (ret != MvError.MV_OK)
                {
                    //LogError($"Open device failed: {ret:x8}");
                    Thread.Sleep(1000);
                    continue;
                }

                // 如果是 GigE 设备，设置最佳包大小
                ConfigureGigEDevice();
                // 设置采集模式为连续模式
                ConfigureAcquisitionMode();
                //// 注册事件并启动采集
                //RegisterDeviceEvents();

                // 开始取流
                Connected = StartGrabbing(AcquisitionMode.Continuous);
            }
        }

        private void ExceptionEventHandler(object sender, DeviceExceptionArgs e)
        {
            if (e.MsgType == DeviceExceptionType.DisConnect)
            {
                Console.WriteLine("Device disconnect!");
                Connected = false;
            }
        }


        #endregion
        #region 方法

        /// <summary>枚举设备</summary>
        private bool TryEnumDevices(out List<IDeviceInfo> deviceInfoList)
        {
            deviceInfoList = null;
            int result = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList);
            if (result != MvError.MV_OK || deviceInfoList == null || deviceInfoList.Count == 0)
            {
                //LogError("Enumerate devices failed!");
                return false;
            }
            return true;
        }

        /// <summary>查找匹配的设备</summary>
        private IDeviceInfo? FindDevice(List<IDeviceInfo> deviceInfoList, string serialNo)
        {
            foreach (var deviceInfo in deviceInfoList)
            {
                if (deviceInfo == null) continue;

                string matchSerialNo = $"{deviceInfo.TLayerType}: {(string.IsNullOrEmpty(deviceInfo.UserDefinedName) ? deviceInfo.ManufacturerName + " " + deviceInfo.ModelName : deviceInfo.UserDefinedName)} ({deviceInfo.SerialNumber})";
                if (serialNo == matchSerialNo)
                {
                    return deviceInfo;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取参数
        /// </summary>
        public override void GetParams()
        {
            GetIpConfig();
            GetWidth();
            GetHeight();
        }

        /// <summary>
        /// 获取宽
        /// </summary>
        public virtual void GetWidth()
        {
            try
            {
                if (device == null)
                {
                    // 创建新设备实例
                    device = DeviceFactory.CreateDevice((IDeviceInfo)ExtInfo);

                    // 打开设备
                    int result = device.Open();
                    if (result != MvError.MV_OK)
                    {
                        //LogError("Open Device failed!");
                        Connected = false;
                        return;
                    }
                }

                if (device.Parameters.GetIntValue("Width", out var widthValue) == MvError.MV_OK)
                {
                    Width = (uint)widthValue.CurValue;
                }
                else
                {
                    //LogWarning("Get Width failed!");
                }

            }
            catch (Exception ex)
            {
                //LogError($"GetWidth failed: {ex.Message}");
                return;
            }
        }

        /// <summary>
        /// 获取高
        /// </summary>
        public virtual void GetHeight()
        {
            try
            {
                if (device == null)
                {
                    // 创建新设备实例
                    device = DeviceFactory.CreateDevice((IDeviceInfo)ExtInfo);

                    // 打开设备
                    int result = device.Open();
                    if (result != MvError.MV_OK)
                    {
                        //LogError("Open Device failed!");
                        Connected = false;
                        return;
                    }
                }

                if (device.Parameters.GetIntValue("Height", out var heightValue) == MvError.MV_OK)
                {
                    Height = (uint)heightValue.CurValue;
                }
                else
                {
                    //LogWarning("Get Width failed!");
                }

            }
            catch (Exception ex)
            {
                //LogError($"GetHeight failed: {ex.Message}");
                return;
            }
        }

        /// <summary> 相机设置</summary>
        public override void SetSetting()
        {
            //设置宽
            SetWidth(Width);
            //设置高
            SetHeight(Height);
            //设置曝光时间
            SetExposureTime(ExposeTime);
            //设置增益
            SetGain(Gain);
        }

        /// <summary>设置宽度</summary>
        public virtual void SetWidth(long value)
        {
            try
            {
                device.Parameters.SetIntValue("Width", value);
            }
            catch (MvdException ex)
            {

            }
        }

        /// <summary>设置高度</summary>
        public virtual void SetHeight(long value)
        {
            try
            {
                device.Parameters.SetIntValue("Height", value);
            }
            catch (MvdException ex)
            {

            }
        }

        /// <summary>设置曝光</summary>
        public override void SetExposureTime(float value)
        {
            try
            {
                device.Parameters.SetEnumValue("ExposureAuto", 0);
                int result = device.Parameters.SetFloatValue("ExposureTime", value);
                if (result != MvError.MV_OK)
                {
                    //ShowErrorMsg("Set Exposure Time Fail!", result);
                }
            }
            catch (MvdException ex)
            {

            }
        }

        /// <summary>设置增益 </summary>
        public override void SetGain(float value)
        {
            try
            {
                device.Parameters.SetEnumValue("GainAuto", 0);
                int result = device.Parameters.SetFloatValue("Gain", value);
                if (result != MvError.MV_OK)
                {
                    //ShowErrorMsg("Set Gain Fail!", result);
                }
            }
            catch (MvdException ex)
            {

            }
        }

        static bool IsMonoPixelFormat(MvGvspPixelType enType)
        {
            switch (enType)
            {
                case MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                    return true;
                default:
                    return false;
            }
        }

        static bool IsColorPixelFormat(MvGvspPixelType enType)
        {
            switch (enType)
            {
                case MvGvspPixelType.PixelType_Gvsp_BGR8_Packed:
                case MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
                case MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR8:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG8:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB8:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG8:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB10:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG10:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG10:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR10:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB12:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG12:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG12:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR12:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
                    return true;
                default:
                    return false;
            }
        }

        #endregion
        #region 销毁

        // 覆盖基类的 Dispose 方法
        public override void Dispose(bool disposing)
        {
            if (!disposedValue)
                try
                {
                    if (disposing)
                    {
                        DisConnectDev();
                        if (reconnectThread != null && reconnectThread.IsAlive)
                        {
                            Connected = false;
                            _bExit = true;
                            reconnectThread.Abort();
                            reconnectThread = null;
                        }
                    }

                    // 调用基类的 Dispose 方法
                    base.Dispose(disposing);

                }
                catch (Exception exception)
                {
                    //Console.WriteLine("FrameGrabedEventHandler exception: " + exception.Message);
                }
        }

        #endregion 


    }
}
